package com.gmail.avereshchaga.transport;

import com.gmail.avereshchaga.cashierdeskconnect.CashierDeskConnect;
import static com.gmail.avereshchaga.tools.Constants.*;
import com.gmail.avereshchaga.transport.entity.Invoice;
import com.gmail.avereshchaga.transport.entity.InvoiceItems;
import com.gmail.avereshchaga.transport.entity.Item;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.http.client.fluent.Form;
import org.apache.http.client.fluent.Request;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.openide.util.Lookup;

/**
 * Class provides the transport function between the client and the server
 *
 * @author <a href="mailto:avereshchaga@gmail.com">Vereshchaga Alexey</a>
 */
public class Client {

    private static List<Invoice> invoices = new ArrayList<Invoice>();
    private static List<InvoiceItems> invoiceItems;
    private static List<Item> items = new ArrayList<Item>();
    private static List<Item> itemsList = new ArrayList<Item>();
    private static List<Item> itemsForEdit = new ArrayList<Item>();
    private String sessionId;
    private String host;

    /**
     * Find all the invoices on the server using the current page
     *
     * @param pageStr current page is a list of invoices
     * @throws IOException
     */
    public void findAllInvoices(String pageStr) throws IOException {
        getSessionAndHost();
        String invoicesURLFull = HTTP + host + INVOICES_URL;
        ObjectMapper mapper = new ObjectMapper();
        String JSONString = Request.Post(invoicesURLFull)
                .bodyForm(Form.form().add("page", pageStr)
                .add("sessionId", sessionId).build())
                .execute().returnContent().asString();
        List<Invoice> invoicesList = mapper.readValue(JSONString, new TypeReference<ArrayList<Invoice>>() {
        });
        invoices.addAll(invoicesList);
    }

    /**
     * Find invoice on the server by id
     *
     * @param idStr id required invoice
     * @throws IOException
     */
    public void findInvoiceById(String idStr) throws IOException {
        getSessionAndHost();
        String invoicesURLFull = HTTP + host + INVOICE_URL;
        Invoice invoice = null;
        ObjectMapper mapper = new ObjectMapper();
        String JSONString = Request.Post(invoicesURLFull)
                .bodyForm(Form.form()
                .add("sessionId", sessionId)
                .add("id", idStr).build())
                .execute().returnContent().asString();
        if (!(JSONString.equals(""))) {
            invoice = mapper.readValue(JSONString, Invoice.class);
        }
        invoices = new ArrayList<Invoice>();
        if (invoice != null) {
            invoices.add(invoice);
        }
    }

    /**
     * Find invoices on the server by filter
     *
     * @param pageStr current page is a list of invoices
     * @param createDateStr date when invoice was created
     * @param createdByStr name who created the invoice
     * @throws IOException
     */
    public void findInvoicesByFilter(String pageStr, String createDateStr, String createdByStr) throws IOException {
        getSessionAndHost();
        String invoicesURLFull = HTTP + host + INVOICES_FILTER_URL;
        ObjectMapper mapper = new ObjectMapper();
        String JSONString = Request.Post(invoicesURLFull)
                .bodyForm(Form.form()
                .add("sessionId", sessionId)
                .add("page", pageStr)
                .add("createDate", createDateStr)
                .add("createdBy", createdByStr).build())
                .execute().returnContent().asString();
        List<Invoice> invoicesList = mapper.readValue(JSONString, new TypeReference<ArrayList<Invoice>>() {
        });
        invoices.addAll(invoicesList);
    }

    /**
     * Find invoices on the server by name who created invoice
     *
     * @param pageStr current page is a list of invoices
     * @param createdByStr name who created the invoice
     * @throws IOException
     */
    public void findInvoicesByName(String pageStr, String createdByStr) throws IOException {
        getSessionAndHost();
        String invoicesURLFull = HTTP + host + INVOICES_BY_NAME_URL;
        ObjectMapper mapper = new ObjectMapper();
        String JSONString = Request.Post(invoicesURLFull)
                .bodyForm(Form.form()
                .add("sessionId", sessionId)
                .add("page", pageStr).add("createdBy", createdByStr).build())
                .execute().returnContent().asString();
        List<Invoice> invoicesList = mapper.readValue(JSONString, new TypeReference<ArrayList<Invoice>>() {
        });
        invoices.addAll(invoicesList);
    }

    /**
     * Find for items in a particular invoice by invoice id
     *
     * @param invoiceIdStr id required invoice
     * @throws IOException
     */
    public void findInvoiceItemsByInvoiceId(String invoiceIdStr) throws IOException {
        getSessionAndHost();
        String invoiceItemsURLFull = HTTP + host + INVOICE_ITEMS_URL;
        ObjectMapper mapper = new ObjectMapper();
        String JSONString = Request.Post(invoiceItemsURLFull)
                .bodyForm(Form.form()
                .add("sessionId", sessionId)
                .add("invoiceId", invoiceIdStr).build())
                .execute().returnContent().asString();
        List<InvoiceItems> invoiceItemsList = mapper.readValue(JSONString, new TypeReference<ArrayList<InvoiceItems>>() {
        });
        invoiceItems = new ArrayList<InvoiceItems>();
        invoiceItems.addAll(invoiceItemsList);
    }

    /**
     * Find all the items on the server using the current page
     *
     * @param itemsPageStr current page is a list of items
     * @throws IOException
     */
    public void findAllItems(String itemsPageStr) throws IOException {
        getSessionAndHost();
        String itemsURLFull = HTTP + host + ITEMS_URL;
        ObjectMapper mapper = new ObjectMapper();
        String JSONString = Request.Post(itemsURLFull)
                .bodyForm(Form.form()
                .add("sessionId", sessionId)
                .add("page", itemsPageStr).build())
                .execute().returnContent().asString();
        List<Item> itemsList = mapper.readValue(JSONString, new TypeReference<ArrayList<Item>>() {
        });
        items.addAll(itemsList);
    }

    /**
     * Save InvoiceItems on the server
     *
     * @throws IOException
     */
    public void saveInvoiceItems() throws IOException {
        getSessionAndHost();
        String saveInvoiceItemsURLFull = HTTP + host + INVOICE_ITEMS_SAVE_URL;
        ObjectMapper mapper = new ObjectMapper();
        String invoiceItemsStr = mapper.writeValueAsString(invoiceItems);
        String JSONString = Request.Post(saveInvoiceItemsURLFull)
                .bodyForm(Form.form()
                .add("sessionId", sessionId)
                .add("invoiceItems", invoiceItemsStr).build())
                .execute().returnContent().asString();
        List<InvoiceItems> invoiceItemsList = mapper.readValue(JSONString, new TypeReference<ArrayList<InvoiceItems>>() {
        });
        invoiceItems = new ArrayList<InvoiceItems>();
        invoiceItems.addAll(invoiceItemsList);
    }

    /**
     * Create invoice on the server
     *
     * @return created invoice
     * @throws IOException
     */
    public Invoice createInvoice() throws IOException {
        getSessionAndHost();
        String createInvoiceURLFull = HTTP + host + INVOICE_CREATE_URL;
        Invoice invoice = new Invoice();
        Date currentDate = new Date();
        ObjectMapper mapper = new ObjectMapper();
        invoice.setCreatedAt(currentDate);
        String invoiceStr = mapper.writeValueAsString(invoice);
        String JSONString = Request.Post(createInvoiceURLFull)
                .bodyForm(Form.form()
                .add("sessionId", sessionId)
                .add("invoice", invoiceStr).build())
                .execute().returnContent().asString();
        invoice = mapper.readValue(JSONString, new TypeReference<Invoice>() {
        });
        return invoice;
    }

    /**
     * Delete invoice on the server by invoice id
     *
     * @param invoiceIdDeleted invoice id for delete
     * @return information about deletion
     * @throws IOException
     */
    public String deleteInvoice(String invoiceIdDeleted) throws IOException {
        getSessionAndHost();
        String deleteInvoiceURLFull = HTTP + host + INVOICE_DELETE_URL;
        String JSONString = Request.Post(deleteInvoiceURLFull)
                .bodyForm(Form.form()
                .add("sessionId", sessionId)
                .add("id", invoiceIdDeleted).build())
                .execute().returnContent().asString();

        if (JSONString.equals(" deleted")) {
            return JSONString;
        } else {
            return " delete error " + JSONString;
        }
    }

    /**
     * Find the items on the server by filter
     *
     * @param code code of item
     * @param name name of item
     * @param createDate date when item was created
     * @param username name of the user who created the item
     * @param pageStr current page is a list of items
     * @throws IOException
     */
    public void findItemsByFilter(String code, String name, String createDate,
            String username, String pageStr) throws IOException {
        getSessionAndHost();
        String findItemsByFilter = HTTP + host + ITEMS_FIND_BY_FILTER;
        ObjectMapper mapper = new ObjectMapper();
        String JSONString = Request.Post(findItemsByFilter)
                .bodyForm(Form.form()
                .add("sessionId", sessionId).add("code", code)
                .add("name", name).add("createDate", createDate).add("username", username)
                .add("page", pageStr).build())
                .execute().returnContent().asString();
        List<Item> items = mapper.readValue(JSONString, new TypeReference<ArrayList<Item>>() {
        });
        itemsList.addAll(items);
    }

    /**
     * Save Items on the server
     *
     * @throws IOException
     */
    public void saveItems() throws IOException {
        getSessionAndHost();
        String saveItemsURLFull = HTTP + host + ITEMS_SAVE_URL;
        ObjectMapper mapper = new ObjectMapper();
        String itemsStr = mapper.writeValueAsString(itemsForEdit);
        Request.Post(saveItemsURLFull).bodyForm(Form.form()
                .add("sessionId", sessionId)
                .add("items", itemsStr).build())
                .execute();
    }

    public void getSessionAndHost() {
        for (CashierDeskConnect cashierDeskConnect : Lookup.getDefault().lookupAll(CashierDeskConnect.class)) {
            host = cashierDeskConnect.getHost();
            sessionId = cashierDeskConnect.getSessionId();
        }
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public static List<Invoice> getInvoices() {
        return invoices;
    }

    public static void setInvoices(List<Invoice> invoices) {
        Client.invoices = invoices;
    }

    public static List<InvoiceItems> getInvoiceItems() {
        return invoiceItems;
    }

    public static void setInvoiceItems(List<InvoiceItems> invoiceItems) {
        Client.invoiceItems = invoiceItems;
    }

    public String getSessionId() {
        return sessionId;
    }

    public void setSessionId(String sessionId) {
        this.sessionId = sessionId;
    }

    public static List<Item> getItems() {
        return items;
    }

    public static void setItems(List<Item> items) {
        Client.items = items;
    }

    public static List<Item> getItemsList() {
        return itemsList;
    }

    public static void setItemsList(List<Item> itemsList) {
        Client.itemsList = itemsList;
    }

    public static List<Item> getItemsForEdit() {
        return itemsForEdit;
    }

    public static void setItemsForEdit(List<Item> itemsForEdit) {
        Client.itemsForEdit = itemsForEdit;
    }
}
